package com.ruoyi.mes.service.impl;

import java.math.BigDecimal;
import java.util.*;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.mes.domain.*;
import com.ruoyi.mes.mapper.*;
import com.ruoyi.mes.service.IProTecService;
import com.ruoyi.mes.utils.RepeatUtils;
import com.ruoyi.mes.vo.product.BomMtrVo;
import com.ruoyi.mes.vo.product.ProTecVo;
import com.ruoyi.mes.vo.product.TecProceVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.mes.service.IProInfoService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 产品信息Service业务层处理
 *
 * @author LongAndHao
 * @date 2023-04-11
 */
@Service
public class ProInfoServiceImpl implements IProInfoService {

    @Autowired
    private ProBomServiceImpl proBomService;

    @Autowired
    private DeviceInfoServiceImpl deviceInfoService;

    @Autowired
    private ProInfoMapper proInfoMapper;

    @Autowired
    private ProBomMapper proBomMapper;

    @Autowired
    private MtrInfoMapper mtrInfoMapper;

    @Autowired
    private ProTecMapper proTecMapper;

    @Autowired
    private IProTecService proTecService;

    @Autowired
    private ProceInfoMapper proceInfoMapper;

    @Autowired
    private ProceMtrMapper proceMtrMapper;


    /**
     * 查询产品信息
     *
     * @param id 产品信息主键
     * @return 产品信息
     */
    @Override
    public ProInfo selectProInfoById(Long id) {
        return proInfoMapper.selectProInfoById(id);
    }

    /**
     * 查询产品信息列表
     *
     * @param proInfo 产品信息
     * @return 产品信息
     */
    @Override
    public List<ProInfo> selectProInfoList(ProInfo proInfo) {
        List<ProInfo> proInfos = proInfoMapper.selectProInfoList(proInfo);
        if (proInfos.size() > 0){
            for (ProInfo info : proInfos) {
                if (info.getBomStatus() != 0) {
                    BigDecimal total = new BigDecimal("0.0");
                    List<MtrInfo> mtrs = getBomAndMtrByProId(info.getId()).getData().getMtrs();//获取产品对应的物料
                    BigDecimal result = null;
                    for (MtrInfo mtr : mtrs) {
                        result = BigDecimal.valueOf(mtr.getMtrQuantity()).multiply(mtr.getCost());//物料成本相加
                        total = total.add(result);
                    }

                    info.setCost(total);
                    proInfoMapper.updateProInfo(info);//更新数据库
                }
            }
        }
        return proInfos;
    }

    /**
     * 新增产品信息
     *
     * @param proInfo 产品信息
     * @return 结果
     */
    @Override
    public int insertProInfo(ProInfo proInfo) {
        //产品编码判重
        Long aLong = proInfoMapper.selectProInfoCountList(proInfo);
        if (aLong != 0) {
            return -1;
        }

        proInfo.setCreateTime(DateUtils.getNowDate());
        //设置默认状态
        proInfo.setBomStatus(0L);
        proInfo.setTecStatus(0L);
        int i = proInfoMapper.insertProInfo(proInfo);
        return i;
    }

    /**
     * 修改产品信息
     *
     * @param proInfo 产品信息
     * @return 结果
     */
    @Override
    public int updateProInfo(ProInfo proInfo) {
        proInfo.setUpdateTime(DateUtils.getNowDate());
        return proInfoMapper.updateProInfo(proInfo);
    }

    /**
     * 批量删除产品信息
     *
     * @param ids 需要删除的产品信息主键
     * @return 结果
     */
    @Override
    public int deleteProInfoByIds(Long[] ids) {
        return proInfoMapper.deleteProInfoByIds(ids);
    }

    /**
     * 删除产品信息信息
     *
     * @param id 产品信息主键
     * @return 结果
     */
    @Override
    public int deleteProInfoById(Long id) {
        return proInfoMapper.deleteProInfoById(id);
    }

    /**
     * 根据产品Id获取Bom及原料信息
     *
     * @param id 产品id
     * @return
     */
    @Override
    public R<BomMtrVo> getBomAndMtrByProId(Long id) {
        //查询产品id相同的Bom集合
        List<ProBom> bomList = proBomMapper.getAlikeBomByProId(id);
        if (bomList.size() == 0) {
            return R.fail("无数据");
        }

        BomMtrVo bomMtrVo = new BomMtrVo();
        bomMtrVo.setProId(id);//产品id

        bomMtrVo.setBomCode(bomList.get(0).getBomCode());//Bom编码


        //原料
        List<MtrInfo> mtrInfos = new ArrayList<>();
        for (ProBom bom : bomList) {
            MtrInfo mtrInfo = mtrInfoMapper.selectMtrInfoById(bom.getMtrId());
            mtrInfo.setMtrQuantity(bom.getMtrQuantity());
            mtrInfos.add(mtrInfo);
        }
        bomMtrVo.setMtrs(mtrInfos);

        return R.ok(bomMtrVo);
    }

    /**
     * 查 - 工艺工序等 - 产品id
     *
     * @param id 产品id。
     * @return
     */
    @Override
    public R<List<TecProceVo>> getTecProceByProId(Long id) {
        //查询产品id相同的工艺集合
        List<ProTec> proTecList = proTecMapper.getAlikeProTecByProId(id);
        if (proTecList.size() == 0) {
            return R.fail("无数据");
        }

        List<TecProceVo> tecProceVos = new ArrayList<>();
        for (ProTec tec : proTecList) {
            TecProceVo tecProceVo = new TecProceVo();
            tecProceVo.setProceSeque(tec.getProceSeque());
            tecProceVo.setTecCode(tec.getTecCode());
            //查询工序
            ProceInfo proceInfo = proceInfoMapper.selectProceInfoById(tec.getProceId());
            tecProceVo.setProceInfo(proceInfo);
            tecProceVos.add(tecProceVo);
        }
        return R.ok(tecProceVos);
    }

    /**
     * 编辑-工艺、工序、原料、设备 (先删后增)
     *
     * @param proTecVo
     * @return
     */
    @Override
    @Transactional
    public AjaxResult editProTecAndMtrs(ProTecVo proTecVo) {
        ProInfo proInfo = proInfoMapper.selectProInfoById(proTecVo.getProId());

        //工序id判重
        List<ProceInfo> infos1 = proTecVo.getProceInfos();
        if (RepeatUtils.isProceIdRepeat(infos1)) {
            return AjaxResult.error("工序重复!");
        }
        //工序顺序判重
        List<ProceInfo> infos2 = proTecVo.getProceInfos();
        if (RepeatUtils.isProceSequeRepeat(infos2)) {
            return AjaxResult.error("工序顺序重复！");
        }

        if (proInfo.getTecStatus() == 0) {
            if (RepeatUtils.isTecCodeRepeat(proTecMapper, proTecVo)) {
                return AjaxResult.error("工艺编码重复！");
            }
            //新增工艺
            proTecService.savetec(proTecVo);
            //覆盖Bom及原料
            coverBomAndMtr(proInfo,proTecVo);
        } else {

            proTecService.edittec(proTecVo);
            //覆盖Bom及原料
            coverBomAndMtr(proInfo,proTecVo);
        }
        //更新工艺查看状态
        proInfo.setTecStatus(1L);
        proInfoMapper.updateProInfo(proInfo);
        return AjaxResult.success("编辑成功!");
    }

    /**
     * 根据工艺编码、工序Id获取原料信息
     *
     * @param tecCode 工艺编码
     * @param proceId 工序id
     * @return
     */
    @Override
    public List<ProceMtr> getMtrByProceId(String tecCode, Long proceId) {
        return proceMtrMapper.getMtrByProceId(tecCode, proceId);
    }

    /**
     * 编辑产品对应的Bom、原料等信息 (先删后增)
     *
     * @param bomMtrVo
     * @return
     */
    @Override
    @Transactional
    public AjaxResult editProBomAndMtrs(BomMtrVo bomMtrVo) {
        ProInfo proInfo = proInfoMapper.selectProInfoById(bomMtrVo.getProId());

        if (proInfo.getBomStatus() == 0) {
            //判断Bom编码是否重复
            if (RepeatUtils.isBomCodeRepeat(proBomMapper, bomMtrVo)) {
                return AjaxResult.error("Bom编码重复！");
            }

            proBomService.saveBom(bomMtrVo);

            //更新状态
            proInfo.setBomStatus(1L);
            proInfoMapper.updateProInfo(proInfo);
        } else {
            //删除原有Bom
            ProBom proBom = new ProBom();
            proBom.setBomCode(bomMtrVo.getBomCode());
            List<ProBom> proBoms = proBomService.selectProBomList(proBom);
            for (ProBom bom : proBoms) {
                proBomService.deleteProBomById(bom.getId());
            }

            proBomService.saveBom(bomMtrVo);
        }

        return AjaxResult.success("编辑成功!");
    }

    /**
     * 查-工艺-产品id
     *
     * @param proId
     * @return
     */
    @Override
    public R<ProTecVo> getProTec(Long proId) {
        ProTecVo proTecVo = new ProTecVo();

        //查询产品id相同的工艺集合
        List<ProTec> proTecList = proTecMapper.getAlikeProTecByProId(proId);
        if (proTecList.size() == 0) {
            return R.fail("无数据");
        }
        //id
        proTecVo.setId(proTecList.get(0).getId());
        //工艺编码
        proTecVo.setTecCode(proTecList.get(0).getTecCode());
        //查询工艺编码相同的集合
        List<ProTec> proTecs = proTecMapper.selectProTecListByTecCode(proTecVo.getTecCode());
        //查询工序
        List<ProceInfo> proceInfos = new ArrayList<>();
        for (ProTec tec : proTecs) {
            ProceInfo proceInfo = proceInfoMapper.selectProceInfoById(tec.getProceId());
            //查询原料
            List<ProceMtr> proceMtrs = proceMtrMapper.getMtrByProceId(proTecVo.getTecCode(), tec.getProceId());
            for (ProceMtr mtr : proceMtrs) {
                mtr.setMtrCode( mtrInfoMapper.selectMtrInfoById(mtr.getMtrId()).getMtrCode());
            }
            proceInfo.setProceMtrs(proceMtrs);
            //查询设备
            List<DeviceInfo> devices = deviceInfoService.getDevicesByProceIdAndTecCode(proTecVo.getTecCode(), tec.getProceId());

            proceInfo.setDeviceInfos(devices);
            proceInfo.setProceSeque(tec.getProceSeque());
            proceInfos.add(proceInfo);
        }

        proTecVo.setProId(proId);
        proTecVo.setProceInfos(proceInfos);
        return R.ok(proTecVo);
    }

    /**
     * 删-产品-产品id
     *
     * @param proId
     * @return
     */
    @Override
    @Transactional
    public AjaxResult deleteProInfo(Long proId) {
        //查出产品id对应的工艺集合
        ProTec proTec = new ProTec();
        proTec.setProId(proId);
        List<ProTec> proTecs = proTecMapper.getProTecsByProId(proId);
        for (ProTec tec : proTecs) {
            //删除原料
            proceMtrMapper.deleteMtrsBtTecAndProce(tec.getTecCode(), tec.getProceId());
            //删除设备
            deviceInfoService.deletDeviceInfoByTecAndProce(tec.getTecCode(), tec.getProceId());
            //删除工艺
            proTecMapper.deleteProTecById(tec.getId());
        }
        //删除Bom
        ProBom proBom = new ProBom();
        proBom.setProId(proId);
        List<ProBom> proBoms = proBomService.selectProBomList(proBom);
        for (ProBom bom : proBoms) {
            proBomService.deleteProBomById(bom.getId());
        }
        proInfoMapper.deleteProInfoById(proId);
        return AjaxResult.success("删除成功！");
    }

    /**
     * 覆盖Bom及原料
     *
     * @param proInfo
     */
    @Override
    public void coverBomAndMtr(ProInfo proInfo, ProTecVo proTecVo) {
        if (proInfo.getBomStatus() != 0) {

            //获取原有Bom编码
            String bomCode = proBomService.getAlikeBomByProId(proInfo.getId()).get(0).getBomCode();
            //删除原有Bom数据
            ProBom proBom = new ProBom();
            proBom.setBomCode(bomCode);
            List<ProBom> proBoms = proBomService.selectProBomList(proBom);
            for (ProBom bom : proBoms) {
                proBomService.deleteProBomById(bom.getId());
            }

            BomMtrVo bomMtrVo = new BomMtrVo();
            bomMtrVo.setProId(proInfo.getId());
            bomMtrVo.setBomCode(bomCode);

            List<MtrInfo> mtrInfos = new ArrayList<>();
            List<ProceInfo> proceInfos = proTecVo.getProceInfos();
            for (ProceInfo proceInfo : proceInfos) {
                List<ProceMtr> proceMtrs = proceInfo.getProceMtrs();
                for (ProceMtr proceMtr : proceMtrs) {
                    MtrInfo mtrInfo = mtrInfoMapper.selectMtrInfoById(proceMtr.getMtrId());

                    //判断物料是否重复，若重复则累加
                    int i = mtrInfos.indexOf(mtrInfo);
                    if (i != -1){
                        MtrInfo info = mtrInfos.get(i);
                        info.setMtrQuantity(info.getMtrQuantity() + proceMtr.getMtrQuantity());
                    }else {
                        mtrInfo.setMtrQuantity(proceMtr.getMtrQuantity());
                        mtrInfos.add(mtrInfo);
                    }

                }
            }
            bomMtrVo.setMtrs(mtrInfos);
            proBomService.saveBom(bomMtrVo);
        }
    }

    @Override
    public ProInfo getProInfoByCode(String proCode) {
        return proInfoMapper.getProInfoByCode(proCode);
    }

}
